package bot {

import java.util.List;
import java.util.Date;
import javax.jdo.Query;
import javax.jdo.PersistenceManager;

import com.google.appengine.api.xmpp.JID;

import scala.collection.immutable.HashMap
import scala.collection.JavaConversions._


object UserManager {
	
	def addUser(jid: JID, nick: String) = {
		var user = new ChatUser(jid, "", false, new Date());

        val pm = PMF.get().getPersistenceManager();

        try {
            pm.makePersistent(user);
        } catch {
          case e: Exception => // TODO: handle this
        } finally {
            pm.close();
        }
        if (nick != null && !nick.equals("")) {
          UserManager.setNick(user.getEmail(), nick);
        }
	}
 
	def deleteUser(jid: JID) {
		// first, get rid of any details
		delInfo(jid)

		val email = getUser(jid).getEmail()
        val pm = PMF.get().getPersistenceManager()
        var query: Query = pm.newQuery(classOf[ChatUser])
		query.setFilter("email == emailParam");
		query.declareParameters("String emailParam");
		query.deletePersistentAll(email);
	}
	
	def addInfo(jid: JID, keyword: String, text: String) = {
		if (getInfoByKeyword(jid, keyword) != null) {
			delInfo(jid, keyword)
		}
		var info = new UserInfo(getUser(jid).getEmail(), keyword, text);

        val pm = PMF.get().getPersistenceManager();

        try {
            pm.makePersistent(info);
        } catch {
          case e: Exception => // TODO: handle this
        } finally {
            pm.close();
        }
	}
	
	def delInfo(jid: JID, keyword: String = null) = {
		val email = getUser(jid).getEmail()
        val pm = PMF.get().getPersistenceManager()
        var query: Query = pm.newQuery(classOf[UserInfo])
        if (keyword == null || keyword.equals("")) {
			query.setFilter("email == emailParam")
			query.declareParameters("String emailParam")
			query.deletePersistentAll(email)        	
        }
        else {
			query.setFilter("email == emailParam && keyword == keywordParam")
			query.declareParameters("String emailParam, String keywordParam")
			query.deletePersistentAll(email, keyword)
        }
	}
	
	def getInfoByKeyword(jid: JID, keyword: String) : String = {
		val email = getUser(jid).getEmail()
        var pm = PMF.get().getPersistenceManager()
        var query = pm.newQuery("select from bot.UserInfo where email == '" + email + 
        														"' && keyword == '" + keyword + "'")
        var infoList = query.execute().asInstanceOf[java.util.List[UserInfo]]
        
        if (infoList.size > 0) {
        	return infoList.get(0).getText()
        }
        
        return null
	}
	
	def getInfo(jid: JID): HashMap[String, String] = {
		var info: HashMap[String, String] = new HashMap
		val email = getUser(jid).getEmail()
        var pm = PMF.get().getPersistenceManager()
        var query = pm.newQuery("select from bot.UserInfo where email == '" + email + "'") 
        var infoList = query.execute().asInstanceOf[java.util.List[UserInfo]]
		
		infoList.foreach(iv => info += iv.getKeyword() -> iv.getText())
		
		return info
	}

	
	def setOnline(jid: JID, online: Boolean, reason: String) : Unit = {
		setOnline(jid.toString(), online, reason);
	}
	
	def setOnline(jid: String, online: Boolean, reason: String) = {
        val pm = PMF.get().getPersistenceManager()
        var reasonMsg = "unknown reason"
        
        try {
            var user: ChatUser = pm.getObjectById(classOf[ChatUser], ChatUser.jid2email(jid));
            user.setOnline(online);
           	user.setLastSeen(new Date());
            if (online) {
            	user.setLastActive(new Date());
            	reasonMsg = "*" + user.getNick() + "* has joined the chat"
            }
            else {
            	reasonMsg = "Offline: *" + user.getNick() + "* (" + reason + ")"
            }
        } catch {
   	          case e: Exception => // TODO: handle this
        }
        finally {
            pm.close();
        }
        showStatus(reasonMsg);
    }
	
	def setLastActive(jid: String) = {
        var pm = PMF.get().getPersistenceManager();
        try {
            var user = pm.getObjectById(classOf[ChatUser], ChatUser.jid2email(jid));
           	user.setLastActive(new Date());
        } catch {
   	          case e: Exception => // TODO: handle this
        } finally {
            pm.close();
        }	
    }
		
	def setNick(jid: JID, nick: String) : String = {
		return setNick(jid.toString(), nick);
	}
	
	def setNick(jid: String, nick: String) : String = {
        var pm = PMF.get().getPersistenceManager();
        var user = getUserByNick(nick);
        var status = "ok";
        if (user == null) {
	        try {
	            var user = pm.getObjectById(classOf[ChatUser], ChatUser.jid2email(jid));
	            user.setNick(nick);
	        } catch {
   	          case e: Exception => status = "failed";
	        } finally {
	            pm.close();
	        }
        }
        else {
        	status = "inuse";
        }
        
        return status;
    }
 
	def getUser(jid: JID) : ChatUser = {
        var pm = PMF.get().getPersistenceManager();
        var user: ChatUser = null
        try {
        	user = pm.getObjectById(classOf[ChatUser], ChatUser.jid2email(jid))
        } catch {
          case e: Exception => user = null
        }
        return user
	}
 
	def getUser(nick: String) : ChatUser = {
		var user = getUserByNick(nick)

		return user
	}
	
	def isOnline(jid: JID) : Boolean = {
		val user = getUser(jid)
		if (user != null) {
			return user.isOnline
		}
		return false
	}
	
	def isRegistered(jid: JID) : Boolean = {
		return getUser(jid) != null
	}
 
	/* @SuppressWarnings("unchecked") */
	def getRegisteredUsers() : java.util.List[ChatUser] = {
		getUsers("select from bot.ChatUser")
	}

	def getLastActive(limit: Int) : java.util.List[ChatUser] = {
		getUsers("select from bot.ChatUser order by lastActive desc limit 0," + limit)
	}
	
	/* @SuppressWarnings("unchecked") */
	def getOnlineUsers() : java.util.List[ChatUser] = {
		getUsers("select from bot.ChatUser where online == true")
	}
	
	private def getUsers(query: String) : java.util.List[ChatUser] = {
        val pm = PMF.get().getPersistenceManager();
        val pmQuery = pm.newQuery(query);
        return pmQuery.execute().asInstanceOf[java.util.List[ChatUser]];		
	}
	
	/* @SuppressWarnings("unchecked") */
	def getUserByNick(nick: String) : ChatUser = {
        var pm = PMF.get().getPersistenceManager();
        
        var query = pm.newQuery("select from bot.ChatUser where nick == '" + nick + "'")

        var users = query.execute().asInstanceOf[java.util.List[ChatUser]]
        
        if (users.size > 0) {
        	return users.get(0);
        }
        
        return null
	}
	
	def showStatus(msg: String) = {
        ConnectionHandler.processStatusMessage("_" + msg + "_");		
	}
	
	def getNick(jid: String) : String = {
        var pm = PMF.get().getPersistenceManager()
        var user: ChatUser = null;
        try {
            user = pm.getObjectById(classOf[ChatUser], ChatUser.jid2email(jid));
        } catch {
   	          case e: Exception => // TODO: handle this
        } finally {
            pm.close();
        }
        
        return if (user != null) user.getNick() else "";
	}
}

} //package bot
